package com.moon.springbootinit.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.moon.springbootinit.common.BaseResponse;
import com.moon.springbootinit.common.ErrorCode;
import com.moon.springbootinit.common.ResultUtils;
import com.moon.springbootinit.exception.BusinessException;
import com.moon.springbootinit.exception.ThrowUtils;
import com.moon.springbootinit.model.dto.post.PostQueryRequest;
import com.moon.springbootinit.model.dto.user.UserQueryRequest;
import com.moon.springbootinit.model.entity.Picture;
import com.moon.springbootinit.model.enums.SearchTypeEnum;
import com.moon.springbootinit.model.search.SearchRequest;
import com.moon.springbootinit.model.vo.PostVO;
import com.moon.springbootinit.model.vo.SearchVO;
import com.moon.springbootinit.model.vo.UserVO;
import com.moon.springbootinit.pattern.SearchFacade;
import com.moon.springbootinit.service.PictureService;
import com.moon.springbootinit.service.PostService;
import com.moon.springbootinit.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.CompletableFuture;

/**
 * 作者博客：<a href="https://blog.csdn.net/weixin_65935065">https://blog.csdn.net/weixin_65935065</a>
 * @author 苦行修士
 */
@RestController
@RequestMapping("/search")
@Slf4j
public class SearchController {

    @Resource
    private PictureService pictureService;

    @Resource
    private PostService postService;

    @Resource
    private UserService userService;

    @Resource
    private SearchFacade searchFacade;

    /**
     * 聚合搜索接口（异步编程）
     * 异步未必响应速度加快，实际测试为主
     *
     * @param searchrequest
     * @return
     */
    @PostMapping("/all01")
    public BaseResponse<SearchVO> searchAll01(@RequestBody SearchRequest searchrequest,HttpServletRequest request) {
        //获取搜索文本
        String searchText = searchrequest.getSearchText();

        //异步查询图片picture
        CompletableFuture<Page<Picture>> pictureTask = CompletableFuture.supplyAsync(() -> {
            //根据搜索文本和分页参数查询图片
            Page<Picture> picturePage = pictureService.searchPicture(searchText, 1, 10);
            return picturePage;
        });

        //异步查询帖子
        CompletableFuture<Page<PostVO>> postTask = CompletableFuture.supplyAsync(() -> {
            //创建帖子查询请求
            PostQueryRequest postQueryRequest = new PostQueryRequest();
            //设置搜索文本
            postQueryRequest.setSearchText(searchText);
            //根据请求参数查询帖子
            Page<PostVO> postVOPage = postService.listPostVOByPage(postQueryRequest, request);
            return postVOPage;
        });

        //异步查询用户
        CompletableFuture<Page<UserVO>> userTask = CompletableFuture.supplyAsync(() -> {
            //创建用户查询请求
            UserQueryRequest userQueryRequest = new UserQueryRequest();
            //设置用户名
            userQueryRequest.setUserName(searchText);
            //根据请求参数查询用户
            Page<UserVO> userVOPage = userService.listUserVOByPage(userQueryRequest);
            return userVOPage;
        });

        //等待所有异步任务完成
        CompletableFuture.allOf(pictureTask, postTask, userTask).join();

        try {
            //获取查询结果
            Page<Picture> picturePage = pictureTask.get();
            Page<PostVO> postVOPage = postTask.get();
            Page<UserVO> userVOPage = userTask.get();

            //创建搜索VO
            SearchVO searchVO = new SearchVO();
            //设置图片列表
            searchVO.setPictureList(picturePage.getRecords());
            //设置帖子列表
            searchVO.setPostList(postVOPage.getRecords());
            //设置用户列表
            searchVO.setUserList(userVOPage.getRecords());
            //返回查询结果
            return ResultUtils.success(searchVO);
        } catch (Exception e) {
            log.error("search error", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"查询异常");
        }
    }


    /**
     * 聚合搜索接口优化
     *
     * 怎么样能让前端又能一次搜出所有数据、又能够分别获取某一类数据（比如分页场景）
     * 新增：前端传type调用后端同一个接口，后端根据type调用不同的service查询
     * 比如：type=user,userService.query
     *
     * 1.如果type为空，那么搜索出所有的数据
     * 2.如果type不为空
     * a.如果type合法，那么查出对应数据
     * b,否则报错
     *
     * @param searchrequest
     * @return
     */
    @PostMapping("/all02")
    public BaseResponse<SearchVO> searchAll02(@RequestBody SearchRequest searchrequest,HttpServletRequest request) {
        //获取搜索类型
        String type = searchrequest.getType();
        //根据搜索类型获取枚举
        SearchTypeEnum searchTypeEnum = SearchTypeEnum.getEnumByValue(type);
        //抛出参数错误
        ThrowUtils.throwIf(StringUtils.isBlank(type),ErrorCode.PARAMS_ERROR);
        //获取搜索文本
        String searchText = searchrequest.getSearchText();
        //搜索出所有数据
        if (searchTypeEnum==null) {
            CompletableFuture<Page<Picture>> pictureTask = CompletableFuture.supplyAsync(() -> {
                //根据搜索文本搜索图片
                Page<Picture> picturePage = pictureService.searchPicture(searchText, 1, 10);
                return picturePage;
            });

            CompletableFuture<Page<PostVO>> postTask = CompletableFuture.supplyAsync(() -> {
                //根据搜索文本搜索帖子
                PostQueryRequest postQueryRequest = new PostQueryRequest();
                postQueryRequest.setSearchText(searchText);
                Page<PostVO> postVOPage = postService.listPostVOByPage(postQueryRequest, request);
                return postVOPage;
            });

            CompletableFuture<Page<UserVO>> userTask = CompletableFuture.supplyAsync(() -> {
                //根据搜索文本搜索用户
                UserQueryRequest userQueryRequest = new UserQueryRequest();
                userQueryRequest.setUserName(searchText);
                Page<UserVO> userVOPage = userService.listUserVOByPage(userQueryRequest);
                return userVOPage;
            });

            //等待所有异步任务完成
            CompletableFuture.allOf(pictureTask, postTask, userTask).join();

            try {
                //获取搜索结果
                Page<Picture> picturePage = pictureTask.get();
                Page<PostVO> postVOPage = postTask.get();
                Page<UserVO> userVOPage = userTask.get();

                //封装搜索结果
                SearchVO searchVO = new SearchVO();
                searchVO.setPictureList(picturePage.getRecords());
                searchVO.setPostList(postVOPage.getRecords());
                searchVO.setUserList(userVOPage.getRecords());
                return ResultUtils.success(searchVO);
            } catch (Exception e) {
                log.error("search error", e);
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"查询异常");
            }
        }else {
            //封装搜索结果
            SearchVO searchVO = new SearchVO();
            switch (searchTypeEnum){
                case USER:
                    //根据搜索文本搜索用户
                    UserQueryRequest userQueryRequest = new UserQueryRequest();
                    userQueryRequest.setUserName(searchText);
                    Page<UserVO> userVOPage = userService.listUserVOByPage(userQueryRequest);
                    searchVO.setUserList(userVOPage.getRecords());
                    break;
                case POST:
                    //根据搜索文本搜索帖子
                    PostQueryRequest postQueryRequest = new PostQueryRequest();
                    postQueryRequest.setSearchText(searchText);
                    Page<PostVO> postVOPage = postService.listPostVOByPage(postQueryRequest, request);
                    searchVO.setPostList(postVOPage.getRecords());
                    break;
                case PICTURE:
                    //根据搜索文本搜索图片
                    Page<Picture> picturePage = pictureService.searchPicture(searchText, 1, 10);
                    searchVO.setPictureList(picturePage.getRecords());
                    break;
                default:
            }
            return ResultUtils.success(searchVO);
        }
    }

    /**
     * 聚合搜索优化（门面模式）
     * @param searchrequest
     * @param request
     * @return
     */
    @PostMapping("/all03")
    public BaseResponse<SearchVO> searchAll03(@RequestBody SearchRequest searchrequest,HttpServletRequest request) {
        return ResultUtils.success(searchFacade.searchAll03(searchrequest, request));

    }

    /**
     * 聚合搜索优化（适配器模式）
     * @param searchrequest
     * @param request
     * @return
     */
    @PostMapping("/all04")
    public BaseResponse<SearchVO> searchAll04(@RequestBody SearchRequest searchrequest,HttpServletRequest request) {
        return ResultUtils.success(searchFacade.searchAll04(searchrequest, request));

    }

}
